<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>cube</title>
</head>

<body>
    <script src="../../test/e2e/js/AssetTool.js"></script>
    <script src="../../test/e2e/js/BasicBoxesTool.js"></script>
    <script src="../../test/e2e/js/LightBoxesTool.js"></script>
    <script src="../../test/e2e/js/PositionTool.js"></script>
    <script src="../../test/e2e/js/LightTool.js"></script>
    <script src="../../test/e2e/js/CameraTool.js"></script>
    <script src="../../test/e2e/js/LightMaterialTool.js"></script>
    <script src="../../dist/wd.js"></script>

    <script>

        window.onload = function () {
            return AssetTool.loadConfig(["../config/setting.json", "../config/"], null, function () {


                // var image = new Image();
                // image.src = "../asset/image/2.png";

                // image.onload = function () {
                //     var imageName = "image_2";
                //     var mimeType = "image/png";

                //     image.name = imageName;


                //     return initSample(
                //         image,
                //         imageName,
                //         _convertImageToUint8Array(image, mimeType),
                //         mimeType,
                //         wd.unsafeGetState());

                // };


                return initSample(
                    wd.unsafeGetState());




            });



            function _init1(script, api, state) {
                var databaseName = "Wonder_Database";
                var tableName = "Wonder_AssetBundle_Cache";
                var cacheFieldName = "Cache";
                var hashIdFieldName = "HashId";
                var abRelativePathFieldName = "ABRelativePath";


                function _getAssetBundlePath() {
                    return "asset_bundle2/";
                };

                function _initAssetBundleArrayBufferCache() {
                    if (!!window.db) {
                        console.log("already init before");

                        return api.fromPromiseStream(
                            new Promise((resolve) => {
                                resolve();
                            }, (reject) => {
                                reject("error");
                            })
                        )
                    };


                    var request = window.indexedDB.open(databaseName);

                    return api.fromPromiseStream(
                        new Promise((resolve, reject) => {
                            request.onerror = (event) => {
                                reject("open database error: ", event.target.errorCode);
                            };

                            request.onsuccess = (event) => {
                                var db = event.target.result;

                                console.log("open onsuccess");

                                window.db = db;

                                resolve();
                            };

                            request.onupgradeneeded = (event) => {
                                var db = event.target.result;

                                console.log("open onupgradeneeded");

                                if (!db.objectStoreNames.contains(tableName)) {
                                    var objectStore = db.createObjectStore(
                                        tableName,
                                        {
                                            keyPath: abRelativePathFieldName,
                                            autoIncrement: false
                                        }
                                    );

                                    // objectStore.createIndex(cacheFieldName, cacheFieldName, { unique: false });
                                    // objectStore.createIndex(hashIdFieldName, hashIdFieldName, { unique: true });
                                    // objectStore.createIndex(abRelativePathFieldName, abRelativePathFieldName, { unique: true });
                                }
                                else {
                                    reject("database->table error: shouldn't exist table: ", tableName);
                                }
                            };
                        })
                    )
                };


                function _isAssetBundleArrayBufferCached(abRelativePath, hashId) {
                    var transaction = window.db.transaction([tableName]);
                    var objectStore = transaction.objectStore(tableName);
                    // var abRelativePath = objectStore.index(abRelativePathFieldName);
                    var request = objectStore.get(abRelativePath);



                    return api.fromPromiseStream(
                        new Promise((resolve, reject) => {
                            request.onerror = (event) => {
                                reject("error: ", event.target.errorCode);
                            };

                            request.onsuccess = (event) => {
                                if (request.result) {

                                    console.log("is cached: ", abRelativePath, request.result[hashIdFieldName] === hashId);

                                    resolve(request.result[hashIdFieldName] === hashId);
                                } else {
                                    console.log("get no data");

                                    resolve(false);
                                }
                            };
                        })
                    )
                };


                function _getAssetBundleArrayBufferCache(abRelativePath) {
                    var transaction = window.db.transaction([tableName]);
                    var objectStore = transaction.objectStore(tableName);
                    // var abRelativePath = objectStore.index(abRelativePathFieldName);
                    // var request = abRelativePath.get(abRelativePath);
                    // var abRelativePath = objectStore.index(abRelativePathFieldName);
                    var request = objectStore.get(abRelativePath);



                    return api.fromPromiseStream(
                        new Promise((resolve, reject) => {
                            request.onerror = (event) => {
                                reject("error: ", event.target.errorCode);
                            };

                            request.onsuccess = (event) => {
                                if (request.result) {

                                    console.log("get cached data:", abRelativePath, request.result[cacheFieldName]);

                                    resolve(request.result[cacheFieldName]);
                                } else {
                                    reject("get no cache")
                                }
                            };
                        })
                    )
                };


                function _cacheAssetBundleArrayBuffer(abRelativePath, ab, hashId) {
                    var transaction = window.db.transaction([tableName], "readwrite");
                    var objectStore = transaction.objectStore(tableName);
                    // var abRelativePath = objectStore.index(abRelativePathFieldName);
                    // var request = abRelativePath.get(abRelativePath);
                    // var request = objectStore.get(abRelativePath);
                    var data = {};
                    data[abRelativePathFieldName] = abRelativePath;
                    data[cacheFieldName] = ab;
                    data[hashIdFieldName] = hashId;

                    var request =
                        objectStore.put(
                            data
                        );


                    return api.fromPromiseStream(
                        new Promise((resolve, reject) => {
                            request.onerror = (event) => {
                                reject("cache fail: ", event.target.errorCode);
                            };

                            request.onsuccess = (event) => {
                                console.log("cache success: ", abRelativePath);

                                resolve();
                            };
                        })
                    )
                };


                // var loadAssetBundle = api.loadAssetBundle;
                // var flatMapStream = api.flatMapStream;

                var sabRelativePath = "sab1.sab";


                var rab1RelativePath = "rab1.rab";
                var rab2RelativePath = "rab2.rab";


                var wabRelativePath = "wab1.wab";



                api.loadWABAndSetToState(
                    wabRelativePath, _getAssetBundlePath
                ).flatMap((wab) => {
                    console.log("wab: ", wab);

                    var manifest = api.parseWABManifest(
                        wab
                    );


                    var wholeDependencyRelationMap =
                        api.getWholeDependencyRelationMap(manifest);

                    var state = api.unsafeGetState();


                    var state =
                        api.setWholeDependencyRelationMap(
                            wabRelativePath,
                            wholeDependencyRelationMap, state
                        );

                    api.setState(state);


                    return
                    api.fromPromiseStream(
                        _initAssetBundleArrayBufferCache()
                    ).concat(
                        api.loadAllDependencyRABAndSetToState(
                            sabRelativePath,
                            manifest,
                            [
                                _getAssetBundlePath,
                                // _initAssetBundleArrayBufferCache,
                                _isAssetBundleArrayBufferCached,
                                _getAssetBundleArrayBufferCache,
                                _cacheAssetBundleArrayBuffer
                            ]
                        ).merge(
                            api.loadSABAndSetToState(
                                sabRelativePath,
                                manifest,
                                [
                                    _getAssetBundlePath,
                                    // _initAssetBundleArrayBufferCache,
                                    _isAssetBundleArrayBufferCached,
                                    _getAssetBundleArrayBufferCache,
                                    _cacheAssetBundleArrayBuffer
                                ]

                            )
                        )
                    ).concat(
                        api.assembleAllDependencyRAB(sabRelativePath, wholeDependencyRelationMap)
                    )


                })
                    .subscribe({
                        "next": _ => {
                            console.log("next")
                        },
                        "error": e => {
                            console.log("error: ", e);
                        },
                        "complete": () => {
                            console.log("complete");
                        }

                    });


                // var scriptAttribute2 =
                //     api.unsafeGetScriptAttribute(
                //         script,
                //         "scriptAttribute2",
                //         state
                //     );

                // var a = api.unsafeGetScriptAttributeFieldValue(
                //     "a",
                //     scriptAttribute2
                // );

                // console.log("init->a: ", a)


                var intervalId = setInterval(() => {
                    var state = api.unsafeGetState();

                    if (!api.isWABLoaded(
                        wabRelativePath,
                        state
                    )) {
                        console.log("wab is not loaded");

                        return;
                    }

                    if (api.canAssembleSAB(
                        sabRelativePath,
                        wabRelativePath,
                        state
                    )) {
                        console.log("assemble sab");

                        clearInterval(intervalId);

                        api.assembleSAB(
                            sabRelativePath,

                            api.unsafeGetLoadedSAB(
                                sabRelativePath, state
                            ),
                            api.unsafeGetWholeDependencyRelationMap(
                                wabRelativePath, state
                            )
                        ).

                            subscribe(
                                {
                                    "next": (sceneGameObject) => {
                                        var state = api.unsafeGetState();

                                        var state = api.initAllSABGameObjects(
                                            sceneGameObject, state
                                        );


                                        // var state =
                                        //     api.disposeSceneAllChildren(state);

                                        // var state =
                                        //     api.setSABSceneGameObjectToBeScene(sceneGameObject, state);


                                        var state =
                                            api.addSABSceneGameObjectChildrenToScene(sceneGameObject, state);


                                        api.setState(state);
                                    },
                                    "error": e => {
                                        console.log("error: ", e);
                                    },
                                    "complete": () => {
                                        console.log("complete");
                                    }
                                }


                            )
                    }
                    else {
                        console.log("sab can't be assembled! need wait",
                            api.getAllNeededABCount(
                                sabRelativePath,
                                wabRelativePath,
                                state,
                            ),
                            api.getLoadedNeededABCount(
                                sabRelativePath,
                                wabRelativePath,
                                state,
                            )
                        )
                    }
                }, 30);





                var intervalId2 = setInterval(() => {
                    var state = api.unsafeGetState();

                    if (api.isRABAssembled(
                        rab1RelativePath, state
                    )) {
                        console.log("get script data from rab1");

                        clearInterval(intervalId2);

                        var scriptEventFunctionData1 =
                            api.unsafeFindScriptEventFunctionDataByName(
                                rab1RelativePath, "scriptEventFunctionData1", state
                            );



                        var scriptAttribute1 =
                            api.unsafeFindScriptAttributeByName(
                                rab1RelativePath, "scriptAttribute1", state
                            );


                        var state =
                            api.replaceScriptEventFunctionData(script,
                                [
                                    "scriptEventFunctionData1", "scriptEventFunctionData1"
                                ],
                                scriptEventFunctionData1, state
                            );



                        var state =
                            api.addScriptAttribute(
                                script,
                                "scriptAttribute1",
                                scriptAttribute1,
                                state
                            );

                        var state =
                            api.initGameObject(
                                api.unsafeGetScriptGameObject(script, state), state
                            );

                        api.setState(state);
                    }
                    else {
                        console.log("rab1 not assembled! need wait");
                    }
                }, 30);



                return state
            };


            function _addScript(box, state) {
                var [state, scriptComponent] = wd.createScript(state);

                var scriptEventFunctionData1 =
                    wd.createScriptEventFunctionData(
                        // "scriptEventFunctionData1"
                        {
                            "init": (script, api, state) => {
                                return _init1(script, api, state);
                            }
                        }
                    );


                // var scriptEventFunctionData1 =
                //     wd.addScriptEventFunctionData(
                //         "update",
                //         (script, api, state) => {
                //             return _update1(script, api, state);
                //         },

                //         scriptEventFunctionData1
                //     );




                var state =
                    wd.addScriptEventFunctionData(
                        scriptComponent,
                        "scriptEventFunctionData1",
                        scriptEventFunctionData1,
                        state

                    );


                var state =
                    wd.addGameObjectScriptComponent(
                        box, scriptComponent, state
                    );

                return state;
            };


            function initSample(
                state) {

                var [state, box] = BasicBoxesTool.createBox(state);

                var transform = wd.unsafeGetGameObjectTransformComponent(box, state);

                var state = wd.setTransformLocalPosition(transform, [-10, 0, 0], state);


                // var record = wd.createBasicSourceTexture(state)
                // var state = record[0];
                // var texture1 = record[1];
                // var textureName = "texture1";
                // var state =
                //     wd.setBasicSourceTextureName(
                //         texture1, textureName, state
                //     );
                // var state = wd.setBasicSourceTextureSource(texture1, image, state);



                // var [state, sphere, sphereGeometry] = createSphere(texture1, state);


                var state = wd.setAmbientLightColor([0.2, 0.2, 0.2], state);


                var [state, directionLightGameObject] = LightTool.createDirectionLight(state);

                var transform = wd.unsafeGetGameObjectTransformComponent(directionLightGameObject, state);

                var state = wd.setTransformLocalEulerAngles(transform, [0, 180, 0], state);




                var [state, cameraGameObject] = LightBoxesTool.createCamera(state);



                var [state, cameraController] = wd.createArcballCameraController(state);

                var state =
                    wd.setArcballCameraControllerDistance(cameraController, 50, state);



                var state =
                    wd.setArcballCameraControllerWheelSpeed(cameraController, 1, state);

                var state = wd.addGameObjectArcballCameraControllerComponent(cameraGameObject, cameraController, state);


                var state =
                    wd.bindArcballCameraControllerEvent(
                        cameraController, state
                    );







                var state = _addScript(box, state);




                var state = wd.addSceneChildren(
                    [
                        // sphere,
                        box,
                        cameraGameObject,
                        directionLightGameObject
                    ],
                    state
                );


                wd.startDirector(state);




                // setTimeout(() => {
                //     var state = wd.unsafeGetState();




                //     var [state, rab] =
                //         wd.generateSingleRAB(
                //             wd.buildResourceData(
                //                 [],
                //                 [],
                //                 [
                //                     [
                //                         texture1,
                //                         0
                //                     ]
                //                 ],
                //                 [
                //                     sphereGeometry
                //                 ],
                //                 [],
                //                 [],
                //                 [
                //                     [
                //                         imageUint8Array,
                //                         imageName, mimeType
                //                     ]
                //                 ],
                //             ),
                //             state
                //         );









                //     var [state, sab] =
                //         wd.generateSingleSAB(
                //             wd.getSceneGameObject(state),
                //             [],
                //             state
                //         );

                //     var rabRelativePath = "rab1.rab";
                //     var sabRelativePath = "sab1.sab";

                //     wd.setState(state);

                //     wd.generateAllABs(
                //         wd.buildDependencyRelation(
                //             [
                //                 [
                //                     sabRelativePath,
                //                     rabRelativePath,

                //                 ]
                //             ]
                //         ),
                //         [
                //             [[
                //                 sabRelativePath, sab
                //             ]],
                //             [[
                //                 rabRelativePath, rab
                //             ]],
                //         ]
                //     )
                //         .subscribe(
                //             {
                //                 "next": (
                //                     [
                //                         wab,
                //                         newRabDataArr,
                //                         newSabDataArr
                //                     ]
                //                 ) => {
                //                     console.log("next",
                //                         wab,
                //                         newRabDataArr,
                //                         newSabDataArr
                //                     );



                //                     AssetTool.download(
                //                         wab,

                //                         "wab1.wab",
                //                     );


                //                     AssetTool.download(
                //                         newRabDataArr[0][1],

                //                         "newRAB1.rab",
                //                     );


                //                     AssetTool.download(
                //                         newSabDataArr[0][1],

                //                         "newSAB1.sab",
                //                     );

                //                 },
                //                 "error": e => {
                //                     console.log("error", e);
                //                 },
                //                 "complete": () => {
                //                     console.log("complete");
                //                 },
                //             }
                //         )



                // }, 500)
            }
        };
    </script>
</body>

</html>